import logging
import os

from sqlalchemy import text
from youtube_transcript_api import YouTubeTranscriptApi

from models.comment_schema import VideoSource
from utils.config_loader import Config
from utils.deepseek_translator import ChatGPTTranslator, DeepSeekTranslator


def _seconds_to_srt_time(seconds: float) -> str:
    hours = int(seconds // 3600)
    minutes = int((seconds % 3600) // 60)
    secs = int(seconds % 60)
    millisecs = int((seconds % 1) * 1000)
    return f"{hours:02d}:{minutes:02d}:{secs:02d},{millisecs:03d}"


def _srt_time_to_seconds(time_str: str) -> float:
    try:
        hh_mm, rest = time_str.rsplit(":", 1)
        hours, minutes = hh_mm.split(":")
        seconds, millis = rest.split(",")
        total = (
            int(hours) * 3600
            + int(minutes) * 60
            + int(seconds)
            + int(millis) / 1000.0
        )
        return total
    except Exception:
        return 0.0


def _write_srt(entries, output_path, text_key: str = "text"):
    lines = []
    for index, entry in enumerate(entries, 1):
        start_time = entry.get("start")
        end_time = entry.get("end")
        text = entry.get(text_key, "")

        lines.append(str(index))
        lines.append(f"{start_time} --> {end_time}")
        lines.append(text.strip())
        lines.append("")

    with open(output_path, "w", encoding="utf-8") as f:
        f.write("\n".join(lines))

    return output_path


def _parse_srt_file(filepath, text_key: str = "text"):
    entries = []
    if not os.path.exists(filepath):
        raise FileNotFoundError(filepath)

    with open(filepath, "r", encoding="utf-8") as f:
        lines = f.read().splitlines()

    start_time = end_time = None
    content_lines = []

    for line in lines + [""]:
        stripped = line.strip()
        if not stripped:
            if start_time and end_time:
                entries.append({
                    "start": start_time,
                    "end": end_time,
                    text_key: " ".join(content_lines).strip()
                })
            start_time = end_time = None
            content_lines = []
            continue

        if stripped.isdigit():
            continue

        if "-->" in stripped:
            parts = stripped.split("-->")
            if len(parts) == 2:
                start_time = parts[0].strip()
                end_time = parts[1].strip()
        else:
            content_lines.append(stripped)

    return entries


def _store_subtitles_to_db(db_manager, source, original_entries, translated_entries, translator):
    """
    将字幕写入数据库并更新处理状态
    """
    if not getattr(source, "id", None):
        logging.info("⚠️ 视频 %s 不在数据库中，跳过入库更新", source.video_id)
        return

    session = db_manager.Session()
    try:
        video_source_id = source.id

        source_lang = getattr(translator, "source_lang", "en")
        target_lang = getattr(translator, "target_lang", "zh-cn")

        session.execute(text("DELETE FROM d_v_subtitles WHERE video_id = :vid"), {"vid": video_source_id})
        session.execute(text("DELETE FROM d_v_full_subtitles WHERE video_id = :vid"), {"vid": video_source_id})

        payload_original = []
        payload_translated = []

        for original, translated in zip(original_entries, translated_entries):
            start_seconds = _srt_time_to_seconds(original.get("start", "00:00:00,000"))
            end_seconds = _srt_time_to_seconds(original.get("end", "00:00:00,000"))

            payload_original.append({
                "video_id": video_source_id,
                "language": source_lang,
                "content": original.get("text", ""),
                "start_time": start_seconds,
                "end_time": end_seconds,
            })

            payload_translated.append({
                "video_id": video_source_id,
                "language": target_lang,
                "content": translated.get("translated") or translated.get("text", ""),
                "start_time": start_seconds,
                "end_time": end_seconds,
            })

        insert_sql = text(
            "INSERT INTO d_v_subtitles (video_id, language, content, start_time, end_time) "
            "VALUES (:video_id, :language, :content, :start_time, :end_time)"
        )
        if payload_original:
            session.execute(insert_sql, payload_original)
        if payload_translated:
            session.execute(insert_sql, payload_translated)

        full_text = "，".join(
            entry.get("translated") or entry.get("text", "")
            for entry in translated_entries
            if (entry.get("translated") or entry.get("text", "")).strip()
        )
        session.execute(
            text("INSERT INTO d_v_full_subtitles (video_id, full_text) VALUES (:video_id, :full_text)"),
            {"video_id": video_source_id, "full_text": full_text}
        )

        session.execute(
            text("UPDATE d_video_sources SET subtitle_processed = 1 WHERE id = :vid"),
            {"vid": video_source_id}
        )

        session.commit()
        logging.info("✅ 数据库已更新视频 %s 的字幕及处理状态", source.video_id)
    except Exception as exc:
        session.rollback()
        logging.error("⚠️ 字幕写入数据库失败: %s", exc)
    finally:
        session.close()


def extract_and_translate_subtitles(db_manager, video_id=None, output_dir="output/subtitles", translator_type="deepseek", skip_translate=False):
    """
    提取并翻译视频字幕，逐条调用翻译接口，保留原始 SRT 结构，同时入库。
    当 skip_translate=True 时，仅使用现有的 .srt 和 _zh.srt 文件写入数据库。
    """
    session = db_manager.Session()
    try:
        if video_id:
            sources = session.query(VideoSource).filter(VideoSource.video_id == video_id).all()
            if not sources:
                logging.info("ℹ️ 数据库中未找到视频 %s，创建临时视频源对象", video_id)
                temp_source = VideoSource(
                    video_id=video_id,
                    platform="youtube",
                    title=f"Temporary source for {video_id}"
                )
                sources = [temp_source]
        else:
            sources = session.query(VideoSource).all()
    finally:
        session.close()

    if not sources:
        logging.warning("⚠️ 没有找到可用的视频源")
        return

    translator = None
    if not skip_translate:
        config = Config()
        translator_type = (translator_type or "deepseek").lower()
        if translator_type == "chatgpt":
            translator = ChatGPTTranslator(api_key=config.OPENAI_API_KEY)
            logging.info("🧠 使用 ChatGPT 进行字幕翻译")
        else:
            translator = DeepSeekTranslator(api_key=config.DEEPSEEK_API_KEY)
            logging.info("🧠 使用 DeepSeek 进行字幕翻译")

    for source in sources:
        logging.info("🎬 开始处理视频 %s", source.video_id)

        video_output_dir = os.path.join(output_dir, source.video_id)
        os.makedirs(video_output_dir, exist_ok=True)

        original_subtitle_path = os.path.join(video_output_dir, f"{source.video_id}.srt")
        zh_subtitle_path = os.path.join(video_output_dir, f"{source.video_id}_zh.srt")

        if skip_translate:
            try:
                original_entries = _parse_srt_file(original_subtitle_path, text_key="text")
                translated_entries = _parse_srt_file(zh_subtitle_path, text_key="translated")
                if len(original_entries) != len(translated_entries):
                    logging.warning("⚠️ 中英文字幕数量不一致，跳过视频 %s", source.video_id)
                    continue
            except Exception as exc:
                logging.error("⚠️ 读取本地字幕失败: %s", exc)
                continue

            dummy_translator = type("DummyTranslator", (), {"source_lang": "en", "target_lang": "zh-cn"})()
            _store_subtitles_to_db(db_manager, source, original_entries, translated_entries, dummy_translator)
            logging.info("✅ 跳过翻译，仅写入数据库完成 视频 %s", source.video_id)
            continue

        # Step 1: 获取原始字幕
        try:
            transcript_data = YouTubeTranscriptApi().fetch(source.video_id)
            logging.info("成功获取 %d 条字幕", len(transcript_data))

            original_entries = []
            for item in transcript_data:
                start_seconds = item.start
                duration = item.duration
                end_seconds = start_seconds + duration
                original_entries.append({
                    "start": _seconds_to_srt_time(start_seconds),
                    "end": _seconds_to_srt_time(end_seconds),
                    "text": item.text
                })
        except Exception as exc:
            logging.warning("⚠️ 无法获取视频 %s 的字幕: %s", source.video_id, exc)
            continue

        # Step 2: 保存原始字幕文件
        try:
            _write_srt(original_entries, original_subtitle_path, text_key="text")
            logging.info("📄 原始字幕已保存: %s", original_subtitle_path)
        except Exception as exc:
            logging.error("⚠️ 保存原始字幕失败: %s", exc)
            continue

        # Step 3: 翻译字幕
        try:
            translated_entries = translator.translate_subtitles(original_entries)
            if not translated_entries:
                logging.warning("⚠️ 翻译失败: %s", source.video_id)
                continue
        except Exception as exc:
            logging.error("⚠️ 翻译过程中出现异常: %s", exc)
            continue

        # Step 4: 保存翻译字幕
        try:
            _write_srt(translated_entries, zh_subtitle_path, text_key="translated")
            logging.info("✅ 视频 %s 字幕已保存至 %s", source.video_id, zh_subtitle_path)
        except Exception as exc:
            logging.error("⚠️ 保存翻译字幕失败: %s", exc)
            continue

        # Step 5: 写入数据库
        _store_subtitles_to_db(db_manager, source, original_entries, translated_entries, translator)
